package org.common.utils.net.netty.http.core;

import com.esotericsoftware.reflectasm.MethodAccess;

import java.lang.reflect.Method;
import java.util.List;
import java.util.Map;

/**
 * 路由信息
 * @author zhouzhibing
 * @date 2025/11/20 20:22
 */
public class RouteInfo {

    /**
     * 路径
     */
    private String path;
    /**
     * 方法索引
     */
    private int methodIndex;
    /**
     * 方法访问器
     */
    private MethodAccess methodAccess;
    /**
     * 方法参数名称
     */
    private List<MethodParam> methodParams;
    /**
     * 路径参数名称
     */
    private List<String> pathParamNames;
    /**
     * 参数数量
     */
    private int paramCount;

    private Object instance;

    public RouteInfo(Object instance, MethodAccess methodAccess, Method method, String path, List<MethodParam> methodParams, List<String> pathParamNames) {
        this.instance = instance;
        this.methodAccess = methodAccess;
        this.paramCount = method.getParameterCount();
        this.methodIndex = methodAccess.getIndex(method.getName(), method.getParameterTypes());
        this.path = path;
        this.methodParams = methodParams;
        this.pathParamNames = pathParamNames;
    }

    public Object invoke(HttpRequest request) {
        if(paramCount == 0) {
            return methodAccess.invoke(instance, methodIndex);
        } else {
            Object [] args = new Object[paramCount];
            for (int i = 0, length = methodParams.size(); i < length; i++) {
                MethodParam methodParam = methodParams.get(i);
                args[i] = getArgValue(request , methodParam);
            }
            return methodAccess.invoke(instance, methodIndex, args);
        }
    }

    private Object getArgValue(HttpRequest request, MethodParam methodParam) {
        Map<String , String> argMap = isPathParam() ? request.getPathParams() : request.getQueryParams();
        String name = methodParam.getName();
        String valueString = argMap.get(name);
        String typeName = methodParam.getType().getName();

        return switch (typeName) {
            case "int" , "java.lang.Integer" -> Integer.valueOf(valueString);
            case "long" , "java.lang.Long" -> Long.valueOf(valueString);
            case "double" , "java.lang.Double" -> Double.valueOf(valueString);
            case "float" , "java.lang.Float" -> Float.valueOf(valueString);
            case "boolean" , "java.lang.Boolean" -> Boolean.valueOf(valueString);
            case "byte" , "java.lang.Byte" -> Byte.valueOf(valueString);
            case "short" , "java.lang.Short" -> Short.valueOf(valueString);
            case "org.common.utils.net.netty.http.core.HttpRequest" -> request;
            default -> valueString;
        };
    }

    public String getPath() {
        return path;
    }

    public int getMethodIndex() {
        return methodIndex;
    }

    public MethodAccess getMethodAccess() {
        return methodAccess;
    }

    public List<String> getPathParamNames() {
        return pathParamNames;
    }

    public List<MethodParam> getMethodParamNames() {
        return methodParams;
    }

    public boolean isPathParam() {
        return pathParamNames != null && !pathParamNames.isEmpty();
    }


}
